package com.studerb.view.tasks.active;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.table.AbstractTableModel;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import com.studerb.events.listener.TaskTableTaskServiceEL;
import com.studerb.tasks.interfaces.ITask;

public class ActiveTasksTableModel extends AbstractTableModel implements PropertyChangeListener {
    public enum Column {TITLE, MESSAGE, STATUS, PROGRESS}

    final private static String[] columnNames = new String[] {"Task Title", "Message", "Status", "Progress"};
    final private static boolean[] isEditable = new boolean[] {false, false, false, false};
    final private static Class[] columnClasses = new Class[] {String.class, String.class, String.class, Object.class};

    @Autowired private ActiveTasksTable activeTasksTable;

    protected List<ITask> tasks = Collections.synchronizedList(new ArrayList<ITask>());
    Logger logger = Logger.getLogger(ActiveTasksTableModel.class);
    TaskTableTaskServiceEL taskServiceEL;

    public synchronized void addTask(ITask task) {
        if(tasks.contains(task)){
            throw new IllegalArgumentException("Task: " + task + " already added to model");
        }
        this.tasks.add(task);
        task.getPropertyChangeSupport().addPropertyChangeListener(this);
        activeTasksTable.addProgressBar();
        fireTableRowsInserted(tasks.size() - 1, tasks.size() - 1);
    }

    public synchronized void cancelTask(int index) {
        ITask task = tasks.get(index);
        boolean cancelled = task.cancel(true);
        logger.debug("Trying to cancel task: " + task + " / returned: " + cancelled);
    }

    @Override public Class<?> getColumnClass(int columnIndex) {
        return columnClasses[columnIndex];
    }

    @Override public int getColumnCount() {
        return columnNames.length;
    }

    @Override public String getColumnName(int columnIndex) {
        return columnNames[columnIndex];
    }

    @Override public int getRowCount() {
        return tasks.size();
    }

    @Override public Object getValueAt(int rowIndex, int columnIndex) {
        ITask task = tasks.get(rowIndex);
        Column column = Column.values()[columnIndex];
        switch(column){
            case TITLE:
                return task.getTitle();
            case PROGRESS:
                return new Integer(task.getProgress());
            case MESSAGE:
                return task.getMessage();
            case STATUS:
                return task.getCurrentState();
            default:
                throw new IllegalArgumentException("Column[TITLE, PROGRESS]: " + columnIndex + " not supported");
        }
    }

    public void init() {
        taskServiceEL = new TaskTableTaskServiceEL(this);
    }

    @Override public boolean isCellEditable(int rowIndex, int columnIndex) {
        return isEditable[columnIndex];
    }

    @Override public void propertyChange(PropertyChangeEvent evt) {
        String propertyName = evt.getPropertyName();
        ITask task = (ITask)evt.getSource();
        int index = tasks.indexOf(task);      
        if(propertyName.equals("progress")){
            fireTableCellUpdated(index, Column.PROGRESS.ordinal());
        }
        else if(propertyName.equals("message")){
            fireTableCellUpdated(index, Column.MESSAGE.ordinal());
        }
        else if(propertyName.equals("status")){
            fireTableCellUpdated(index, Column.STATUS.ordinal());
        }
        else if(propertyName.equals("title")){
            fireTableCellUpdated(index, Column.TITLE.ordinal());
        }
    }

    public synchronized void removeTask(ITask t) {
        int taskIndex = tasks.indexOf(t);
        if(taskIndex == -1){
            logger.warn("Tasks does not contain task: " + t.toString() + "\tIgnoring Task");
            return;
        }
        this.tasks.remove(t);
        activeTasksTable.removeProgressBar(taskIndex);
        t.getPropertyChangeSupport().removePropertyChangeListener(this);
        fireTableRowsDeleted(taskIndex, taskIndex);
    }

    @Override public void setValueAt(Object value, int rowIndex, int columnIndex) {
        throw new UnsupportedOperationException("Task Table does not have editable table cells");
    }
    
    public ITask getTask(int i){
    	return this.tasks.get(i);
    }
}